<template>
    <canvas ref="canvas" width="100" height="100" class="p-painter-contours"></canvas>
</template>

<script>
import * as enums from '../store/status-enums.js';
import { mapState } from 'vuex';
import _ from 'lodash';
import bus from '../utils/Eventbus.js';
import Point from '../utils/Point.js';
import * as Utils from '../core/utils.js';
import * as Matrix from '../utils/Matrix.js';
import * as Painter from '../core/Painter.js';
import TapeMeasure from '../core/TapeMeasure.js';

/**
 * p-painter-contours
 * @author wangdasong
 * @date 2023.01.30
 */
export default {
    name: 'p-painter-contours',
    components: {},
    props: {
        // display mode of the map, can be '2d' or 'isometric', default is '', means '2d', maybe '3d' in the future.
        mode: {
            type: String,
            default: ''
        },
        value: Array, // local offline data
        map: Object, // map arguments
        offline: Boolean,
        scalingable: {
            type: Boolean,
            default: true
        },
        draggable: {
            type: Boolean,
            default: true
        },
        tapeMode: Boolean, // Tape measure.
        hideContours: Boolean,
        hideRanges: Boolean
    },
    data() {
        return {
            trueName: this.$options.name,
            matrix: null,
            ctx: null,
            ratio: null,
            dimensions: null, // [-10000, 10000, -10000, 10000],
            timer: null,
            refreshing: false,
            local: {}, // local drawing before submit ...
            localList: [],
            tape: null,
            tapes: []
        };
    },
    computed: {
        ...mapState({
            currentContours: state => state.businessStatus.selectedContours,
            currentRanges: state => state.businessStatus.selectedRanges,
            displayContourLayers: state => state.businessStatus.displayContourLayers,
            displayRangeLayers: state => state.businessStatus.displayRangeLayers,
            isDrawContoursActive: state => state.businessStatus.isDrawContoursActive,
            isDrawRangesActive: state => state.businessStatus.isDrawRangesActive,
            isMultiSelectActive: state => state.businessStatus.isMultiSelectActive,
            isAltFnActive: state => state.businessStatus.isAltFnActive
        })
        // isometric() {
        //     return this.mode === 'isometric';
        // }
    },
    watch: {
        hideContours(val) {
            console.log('p-painter-contours.watch.hideContours: ', val);
            this.setCtxCache('');
        },
        hideRanges(val) {
            console.log('p-painter-contours.watch.hideRanges: ', val);
            this.setCtxCache('');
        }
    },
    created() {
        if (!this.offline) bus.on(`${this.trueName}.refresh`, this.refresh);
        bus.on(`${this.trueName}.locateContour`, this.locateContour);
        bus.on(`${this.trueName}.locateRanges`, this.locateRanges);
        bus.on(`${this.trueName}.undo`, this.undo);
    },
    beforeDestroy: function() {
        if (this.timer) cancelAnimationFrame(this.timer);
        // 清除事件监听
        bus.off(`${this.trueName}.refresh`, this.refresh);
        bus.off(`${this.trueName}.locateContour`, this.locateContour);
        bus.off(`${this.trueName}.locateRanges`, this.locateRanges);
        bus.off(`${this.trueName}.undo`, this.undo);
    },
    mounted() {
        this.init();
    },
    methods: {
        init() {
            console.log('p-painter-contours.init: ', this._uid, this.dimensions);
            this.initCanvas();
        },
        initCanvas() {
            //             // console.log('contours.initCanvas: ', this._uid, this.map.width, this.$parent.$el.clientWidth);

            let obj = this.$refs.canvas;
            if (!this.ctx) this.ctx = obj.getContext('2d');
            if (!this.ratio) this.ratio = Matrix.getPixelRatio(this.ctx);
            // // let w = parseInt(this.$parent.$el.clientWidth, 10),
            // //     h = parseInt(this.$parent.$el.clientHeight, 10),
            // let w = parseInt(getComputedStyle(obj.parentNode).width || 100, 10),
            //     h = parseInt(getComputedStyle(obj.parentNode).height || 100, 10),
            //     mw = window.document.body.offsetWidth,
            //     mh = window.document.body.offsetHeight;
            // w = Math.min(w, mw) * this.ratio;
            // h = Math.min(h, mh) * this.ratio;
            // if (obj.width === w && obj.height === h) return;
            // obj.setAttribute('width', w);
            // obj.setAttribute('height', h);
            // console.log('contours.initCanvas: ', obj.width, w, mw, obj.height, h, mh);
            let w = parseInt(this.$parent.$el.clientWidth, 10) * this.ratio,
                h = parseInt(this.$parent.$el.clientHeight, 10) * this.ratio;
            if (obj.width === w && obj.height === h) return;
            obj.setAttribute('width', w);
            obj.setAttribute('height', h);
        },

        initCanvasCtx(ctx = this.ctx) {
            let cp = new Point(this.map.originX, this.map.originY);
            // if (this.isometric) cp = Point.getIsometricPos(cp.x, cp.y);
            ctx.translate(cp.x, cp.y);
            ctx.scale(this.map.scaling, this.map.scaling);
            ctx.rotate(this.map.rotation * (Math.PI / 180));
            // console.log('p-painter-paths.initCanvasCtx: ', cp);
        },

        repaint(recalculate = false) {
            console.log('p-painter-contours.repaint: ');
            if (recalculate) {
                //
            } else {
                this.dimensions = null;
            }
            this.init();
        },
        clearLocals() {
            this.local = {};
            this.localList = [];
        },
        // isPointInStroke(cusPos, contours = []) {
        //     let rtn = null;
        //     if (!cusPos) return;
        //     this.refreshing = true;
        //     console.log('p-painter-contours.isPointInStroke: ', cusPos, contours);

        //     this.ctx.save();
        //     this.initCanvasCtx();
        //     // console.error(contours);
        //     if (!this.lastSelectedIdx || this.lastSelectedIdx < 0) this.lastSelectedIdx = contours.length - 1;
        //     for (let i = this.lastSelectedIdx; i >= 0; i--) {
        //         console.log('p-painter-contours.isPointInStroke: ', this.lastSelectedIdx, i, contours[i]);
        //         Painter.drawContours(this.ctx, contours[i], this.map, this.isometric);
        //         if (cusPos && this.ctx.isPointInPath(cusPos.x, cusPos.y)) {
        //             this.lastSelectedIdx = i - 1;
        //             rtn = contours[i];
        //             break;
        //         }
        //     }
        //     this.ctx.restore();
        //     if (!rtn) this.lastSelectedIdx = null;
        //     // if (!this.lastSelectedIdx || this.lastSelectedIdx >= contours.length) this.lastSelectedIdx = 0;
        //     // for (let i = this.lastSelectedIdx; i < contours.length; i++) {
        //     //     Painter.drawContours(this.ctx, contours[i], this.map, this.isometric);
        //     //     if (cusPos && this.ctx.isPointInPath(cusPos.x, cusPos.y)) {
        //     //         this.lastSelectedIdx = i + 1;
        //     //         rtn = contours[i];
        //     //         break;
        //     //     }
        //     // }
        //     // this.ctx.restore();
        //     // if (!rtn) this.lastSelectedIdx = 0;
        //     this.refreshing = false;
        //     return rtn;
        // },
        isPointInStroke(cusPos, type = 'contours') {
            let rtn = null;
            if (!cusPos) return;
            this.refreshing = true;
            let resources = type === 'contours' ? this.$root.resources.contours : this.$root.resources.ranges || [],
                idxStr = 'last' + type + 'Idx';
            // console.log('p-painter-contours.isPointInStroke: ', cusPos, resources);

            this.ctx.save();
            this.initCanvasCtx();
            if ((!this[idxStr] && this[idxStr] !== 0) || this[idxStr] < 0 || this.isAltFnActive)
                this[idxStr] = resources.length - 1;
            for (let i = this[idxStr]; i >= 0; i--) {
                // console.log('p-painter-contours.isPointInStroke: ', this[idxStr], i, resources[i]);
                Painter.drawContours(this.ctx, resources[i], this.map, this.isometric);
                if (cusPos && this.ctx.isPointInPath(cusPos.x, cusPos.y)) {
                    this[idxStr] = i - 1;
                    rtn = resources[i];
                    break;
                }
            }
            this.ctx.restore();
            if (!rtn) this[idxStr] = null;
            this.refreshing = false;
            return rtn;
        },
        refresh(updatedTag) {
            //eslint-disable-line
            // console.log('p-painter-contours.refresh ... ', this.$refs.canvas.width);
            // console.log('p-painter-contours.refresh ... ', updatedTag);
            if (this.refreshing || !this.ctx) return;
            // if (!this.$root.resources.contours) return;
            this.refreshing = true;
            this.initCanvas();
            // console.log('p-painter-contours.refresh: ');

            // Isometric logic.
            let cp = new Point(this.map.originX, this.map.originY);
            // if (this.isometric) cp = Point.getIsometricPos(cp.x, cp.y);

            // Offscreen Render.
            let key = `${this.map.width}_${this.map.height}_${cp.x}_${cp.y}_${this.map.scaling}_${this.map.rotation}_${this.currentContours}_${this.currentRanges}`,
                // img = BlobHelper.getContoursCache(key);
                img = this.getCtxCache(key);

            // refresh when the local points not empty
            if ((this.local && this.local.points && this.local.points.length) || this.localList.length)
                updatedTag = true; //eslint-disable-line
            // refresh when the tape points not empty
            if ((this.tape && this.tape.points && this.tape.points.length) || this.tapes.length) updatedTag = true; //eslint-disable-line

            // console.log('p-painter-contours.refresh: ', this.delayRenderNum);
            // if no move && no updates, then is't refresh after some times.
            if (img && !updatedTag && this.delayRenderNum > 10) return (this.refreshing = false);

            if (!img || updatedTag) {
                this.delayRenderNum = 0;
                img = this.offscreenRender(key);
            }
            this.ctx.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
            if (!this.$refs.canvas || !this.$refs.canvas.width) return (this.refreshing = false);
            this.ctx.drawImage(img, 0, 0);
            this.delayRenderNum++;

            // dynamic render, like selected style
            // this.dynamicRender();

            this.refreshing = false;
        },
        // dynamicRender() {},
        offscreenRender(key) {
            if (!this.offCvs) this.offCvs = document.createElement('canvas');
            if (this.offCvs.width !== this.$refs.canvas.width)
                this.offCvs.setAttribute('width', this.$refs.canvas.width);
            if (this.offCvs.height !== this.$refs.canvas.height)
                this.offCvs.setAttribute('height', this.$refs.canvas.height);
            this.offCvsCtx = this.offCvs.getContext('2d');
            this.offCvsCtx.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
            this.offCvsCtx.save();

            // Isometric logic.
            let cp = new Point(this.map.originX, this.map.originY);
            // if (this.isometric) cp = Point.getIsometricPos(cp.x, cp.y);
            this.offCvsCtx.translate(cp.x, cp.y);
            this.offCvsCtx.scale(this.map.scaling, this.map.scaling);
            this.offCvsCtx.rotate(this.map.rotation * (Math.PI / 180));
            // this.offCvsCtx.save();

            this.offCvsCtx.lineWidth = 10.5;
            this.offCvsCtx.strokeStyle = 'rgba(0, 0, 0, 0.5)';

            // paint ranges
            let rangesResources = this.value ? this.value : this.$root.resources.ranges;
            if (!rangesResources || !rangesResources.length) rangesResources = [];
            rangesResources = JSON.parse(JSON.stringify(rangesResources));
            // recaculate array sequence order by layer number before painting. 
            if (rangesResources && rangesResources.length > 0) rangesResources.sort((a, b) => a.layer - b.layer);
            (rangesResources || []).forEach(r => {
                if (typeof this.displayRangeLayers === 'number' && r.layer !== this.displayRangeLayers) return;
                if (!this.hideRanges) {
                    this.drawContour(this.offCvsCtx, r, 'ranges');
                    this.drawSelected(this.offCvsCtx, r, 'ranges');
                    this.drawLabel(this.offCvsCtx, r, 'ranges');
                }
            });

            // paint contours
            let contoursResources = this.value ? this.value : this.$root.resources.contours;
            if (!contoursResources || !contoursResources.length) contoursResources = [];
            contoursResources = JSON.parse(JSON.stringify(contoursResources));
            // recaculate array sequence order by layer number before painting. 
            if (contoursResources && contoursResources.length > 0) contoursResources.sort((a, b) => a.layer - b.layer);
            (contoursResources || []).forEach(o => {
                // show current layers, control in contours page...
                if (typeof this.displayContourLayers === 'number' && o.layer !== this.displayContourLayers) return;
                // if (o.id === '1') console.log('p-painter-contours.refresh: ', o);
                if (!this.hideContours) {
                    this.drawContour(this.offCvsCtx, o);
                    // 选中效果
                    this.drawSelected(this.offCvsCtx, o);
                    // label
                    this.drawLabel(this.offCvsCtx, o);
                }
            });

            this.drawLocals(this.offCvsCtx);

            // Draw tape measure. 
            this.drawTapeMeasure();

            this.offCvsCtx.restore();

            // set canvas cache. 
            this.setCtxCache(key, this.offCvs);

            return this.offCvs;
        },
        drawTapeMeasure() {
            // Draw tape measure.
            if (!this.tapeMode) return;
            if (this.tapes && this.tapes.length) {
                this.tapes.forEach(t => {
                    t.lineWidth = (1 / this.map.scaling) * 2 || 100;
                    t.draw();
                    t.drawPoints();
                    t.drawController();
                });
            }
            if (this.tape) {
                this.tape.draw();
                // this.tape.drawPoints();
                // this.tape.drawController();
            }
            this.delayRenderNum = 0; // means refresh will continue for a while. 
        },
        drawContour(ctx, o, type = 'contours') {
            ctx.save();
            // shape
            ctx.beginPath();
            // // Isometric logic. 
            // let ps = o[this.is.
            let ps = o.points || [];
            ps.forEach((p, i) => {
                ctx[i === 0 ? 'moveTo' : 'lineTo'](p.x, -p.y);
            });
            if (ps && ps.length > 1) ctx.lineTo(ps[0].x, -ps[0].y);
            ctx.fillStyle = o.color;
            ctx.fill();
            let penSize = 1 / this.map.scaling || 100;
            ctx.strokeStyle = o.strokeStyleExt;
            if (type === 'ranges') {
                ctx.setLineDash([penSize * 20, penSize * 20]);
                ctx.lineCap = 'round';
                ctx.lineWidth = penSize * 10;
                ctx.stroke();
            } else if (ps.length === 2) {
                ctx.lineWidth = penSize * 5;
                ctx.stroke();
            }
            ctx.closePath();
            ctx.restore();
        },
        // local contours
        drawLocals(ctx) {
            ctx.save();
            if (this.local && this.local.points && this.local.points.length) {
                let penSize = 1 / this.map.scaling || 100;
                this.local.points.forEach(p => {
                    ctx.beginPath();
                    ctx.arc(p.x, -p.y, penSize * 5, 0, -Math.PI * 2);
                    ctx.fillStyle = 'rgba(0,0,0,0.85)';
                    ctx.fill();
                    ctx.closePath();
                });
                ctx.beginPath();
                this.local.points.forEach((p, i) => {
                    ctx[i === 0 ? 'moveTo' : 'lineTo'](p.x, -p.y);
                });
                if (this.local.type === 'ranges') ctx.setLineDash([penSize * 20, penSize * 20]);
                ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)';
                ctx.lineWidth = penSize * 5;
                ctx.stroke();
                ctx.closePath();
            }

            if (this.localList && this.localList.length) {
                this.localList.forEach(o => {
                    this.drawContour(ctx, o);
                });
            }
            ctx.restore();
        },
        drawLabel(ctx, o, type = 'contours') {
            if (!o.label) return;
            let labs = (this.$root.resources && this.$root.resources[type + 'Labels']) || {},
                l = labs[o.id] || null;
            if (!l) return;
            ctx.save();

            Painter.drawContourLabel(ctx, l, l.textFillExt);

            ctx.restore();
        },
        drawSelected(ctx, o, type = 'contours') {
            if (type === 'contours' && (!this.currentContours.length || this.currentContours.indexOf(o.id) < 0)) return;
            else if (type === 'ranges' && (!this.currentRanges.length || this.currentRanges.indexOf(o.id) < 0)) return;

            // // Isometric logic. 
            // let ps = o[this.isometric ? 'iPointsExt' : 'points'];
            let ps = o.points || [];

            ctx.save();
            ctx.lineWidth = o.strokeWidthExt;
            ctx.beginPath();
            ps.forEach((p, i) => {
                if (i === 0) ctx.moveTo(p.x, -p.y);
                ctx.lineTo(p.x, -p.y);
            });
            ctx.lineTo(ps[0].x, -ps[0].y);
            ctx.strokeStyle = o.strokeExt;
            ctx.stroke();
            ctx.closePath();
            ctx.restore();
        },
        locateContour(id) {
            if (!id) return;
            let o = this.$root.resources.contours.find(v => v.id === id),
                d = Matrix.getContourDimensions([o], null, this.ratio),
                zoomed = [d[0] - 10000, d[1] + 10000, d[2] - 10000, d[3] + 10000];
            console.log('p-painter-contours.locateContour: ', id, o, d, zoomed);
            this.$emit('dimensionsChange', zoomed);
        },
        locateRanges(id) {
            if (!id) return;
            let o = this.$root.resources.ranges.find(v => v.id === id),
                d = Matrix.getContourDimensions([o], null, this.ratio),
                zoomed = [d[0] - 10000, d[1] + 10000, d[2] - 10000, d[3] + 10000];
            // console.log('p-painter-contours.locateRanges: ', id, o, d, zoomed);
            this.$emit('dimensionsChange', zoomed);
        },

        // draw contour or range
        pointerDownFunc(cursorPos, transPos, type = 'contours') {
            if (this.isMultiSelectActive) {
                this.startPoint = transPos;
            } else if (this.tapeMode) {
                this.startPoint = transPos;
                // tape mode. 
                this.tapePointIdx = -1;
                if (this.tapes && this.tapes.length) {
                    for (let i = this.tapes.length - 1; i >= 0; i--) {
                        this.tapePointIdx = this.tapes[i].isInPath(transPos, this.map.scaling);
                        if (this.tapePointIdx > -1) {
                            this.tape = this.tapes[i];
                            return true;
                        }
                    }
                }
                // console.log('p-painter-pointerDownFunc: ', this.tapeMode, this.tape, this.tapes, this.tapePointIdx);
                if (!this.tape && this.tapePointIdx < 0) {
                    this.tape = new TapeMeasure({
                        ctx: this.offCvsCtx,
                        ctxWidth: this.$refs.canvas.width,
                        ctxHeight: this.$refs.canvas.height,
                        ratio: this.ratio,
                        pos: transPos,
                        lineWidth: (1 / this.map.scaling) * 2 || 100,
                        scaling: this.map.scaling
                    });
                    // this.tapePointIdx = this.bezier.isInPath(tp, this.map.scaling);
                    this.tapes.push(this.tape);
                }
                // console.warn('=======>  ', this.tapes, this.tapePointIdx);
                this.delayRenderNum = 0; // means refresh will continue for a while. 
            } else if (this.isDrawContoursActive || this.isDrawRangesActive) {
                this.startPoint = transPos;

                let pos = this.getAnchor(transPos);
                // console.log('p-painter-contours.pointerDownFunc: ', pNow, cNow, pos, this.local);
                // console.error(this.isDrawContoursActive, this.isDrawRangesActive);
                if (this.isDrawContoursActive || this.isDrawRangesActive) {
                    if (
                        this.local &&
                        this.local.points &&
                        this.local.points.length &&
                        pos.equals(this.local.points[0])
                    ) {
                        if (this.local.points.length >= 3) {
                            // siteMap.removeDrawMarker(this.local);
                            // this.local.layer非源代码中的代码，根据需求新增的，主要处理自定义图形在最上层
                            this.local.layer = 3;
                            // this.createContour(this.local);

                            this.localList.push(this.local);
                            this.local = {};
                            // this.$store.commit(enums.OPEN_BOX, 'contourEditor');
                            if (type === 'ranges') this.$emit('drawRanges', _.cloneDeep(this.localList));
                            else this.$emit('drawContours', _.cloneDeep(this.localList));
                            // bus.emit('contoursEditor.create', _.cloneDeep(this.localList));
                        }
                    } else if (
                        !Object.keys(this.local).length ||
                        !this.local.points ||
                        !pos.equals(this.local.points[this.local.points.length - 1])
                    ) {
                        // console.log('p-painter-contours.pointerDownFunc: ', this.local.points);
                        if (!this.local.points || !this.local.points.length)
                            this.local = this.getTemplate();
                        // mark the type, contours or ranges
                        this.local.type = type;
                        this.local.points.push(pos);
                    }
                }
            }
        },
        // // only for multi select ...
        pointerMoveFunc(cursorPos, transPos) {
            if (this.tapeMode && this.tape && this.pointerButton !== 2) {
                if (this.tapePointIdx > -1) {
                    // this.tape.update(this.tapePointIdx, tcp);
                    this.tape.update(this.tapePointIdx, transPos);
                } else {
                    // console.log('---> ', tcp, this.tape.points);
                    // this.tape.initUpdate(this.startPoint, tcp);
                    this.tape.initUpdate(this.startPoint, transPos);
                }
                let p1 = this.tape.points[0],
                    p2 = this.tape.points[this.tape.points.length - 1];
                let stp = new Point(p1.x, p1.y);
                let dist = stp.distance(p2);
                if (dist > 100) dist = (dist / 1000).toFixed(2) + 'm';
                else dist = parseInt(dist) + 'mm';
                this.tape.labels = dist;
                this.delayRenderNum = 0; // means refresh will continue for a while.
            }
        },
        // only for multi select ...
        pointerUpFunc(cursorPos, transPos, type = 'contours') {
            // console.log('p-painter-contours.pointerUpFunc: ');
            this.multiSelect(cursorPos, transPos, type);
            this.tape = null;
            this.tapePointIdx = -1;
        },
        pointerLeaveFunc() {
            // console.log('p-painter-contours.pointerLeaveFunc: ');
            this.tape = null;
            this.tapePointIdx = -1;
        },
        multiSelect(cursorPos, transPos, type) {
            /*
             * Q: 'x' of null
             * A: pos0 or pos1 of null
             */
            if (!cursorPos || !transPos || !this.startPoint || !this.isMultiSelectActive) return;
            let pos0 = this.startPoint,
                pos1 = transPos,
                p0 = {},
                p1 = {};
            this.startPoint = null;
            // console.warn('p-painter-contours.multiSelect: ', pos0, pos1);

            p0.x = Math.min(pos0.x, pos1.x);
            p0.y = Math.min(pos0.y, pos1.y);
            p1.x = Math.max(pos0.x, pos1.x);
            p1.y = Math.max(pos0.y, pos1.y);
            let selects = [];

            if (!this.$root.resources[type] || !this.$root.resources[type].length) return;
            this.$root.resources[type].forEach(c => {
                if (!c.points || !c.points.length) return;
                let tag = true;
                c.points.some(p => {
                    if (p.x < p0.x || p.x > p1.x || p.y < p0.y || p.y > p1.y) {
                        tag = false;
                        return true;
                    }
                });
                if (tag) selects.push(c.id);
            });
            console.warn('p-painter-contours.pointerUpFunc: ', p0, p1, selects);
            if (selects && selects.length && type === 'ranges') this.$store.commit(enums.DESELECT_RANGES_ALL, selects);
            else this.$store.commit(enums.DESELECT_CONTOURS_ALL, selects);
            this.$emit(type + 'Change', selects);
        },
        getPolygonPoints(c) {
            let cp = c.points,
                pp = '';
            for (let i = 0; i < cp.length; i++) pp += cp[i].x + ',' + cp[i].y + ' ';
            return pp;
        },
        getAnchor(cursorPos) {
            // let gridSpacing = this.mapGrid.spacing,
            let gridSpacing = this.$parent.getGridSpacing(),
                anchor = new Point();

            anchor.x = Math.round(cursorPos.x / gridSpacing) * gridSpacing;
            anchor.y = Math.round(cursorPos.y / gridSpacing) * gridSpacing;
            // console.log('p-painter-contours.getAnchor: --------> ', cursorPos, gridSpacing, anchor);

            let minDistance = cursorPos.distance(anchor),
                distance,
                p,
                pool = this.localList.slice();
            pool.push.apply(pool, this.$root.resources.contours);

            for (let i = 0; i < pool.length; i++) {
                for (let k = 0; k < pool[i].points.length; k++) {
                    p = pool[i].points[k];
                    distance = cursorPos.distance(p);
                    if (distance < minDistance) {
                        anchor = new Point(p.x, p.y);
                        minDistance = distance;
                    }
                }
            }
            return anchor;
        },
        getTemplate() {
            if (!this.template) {
                if (!this.$root.resources || !this.$root.resources.contours || !this.$root.resources.contours.length) {
                    this.template = {};
                    this.template.layer = 0;
                    this.template.color = 'rgba(0,0,0,0.25)';
                    this.template.labelColor = 'rgba(0,0,0,0)';
                    this.template.labelOffset = new Point(0, 0);
                    this.template.m3d = '';
                    this.template.m3dScale = '';
                    this.template.m3dOffset = {
                        x: 0,
                        y: 0,
                        z: 0,
                        h: 0
                    };
                    this.template.m3dHeight = 0;
                    // "m3dScale":"","m3dHeight":0,m3dOffset":{"x":0,"y":0,"z":0,"h":0}
                } else {
                    // let index = this.$root.resources.contours.length;
                    // while (index--) {
                    //     if (!this.template) this.template = this.$root.resources.contours[index];
                    //     else if (this.$root.resources.contours[index].responsibility === REST.username) {
                    //         this.template = this.$root.resources.contours[index];
                    //         break;
                    //     }
                    // }
                    let index = this.$root.resources.contours.length;
                    this.template = this.$root.resources.contours[index - 1];
                }
            }
            delete this.template.initTime;
            let c = JSON.parse(JSON.stringify(this.template));

            let sess = Utils.getSessionStorage('CREDENTIALS'),
                username = sess.get('username');

            c.id = 'local_' + this.localList.length;
            // 实际开发中，后台会返回唯一的Id,而目前由于数据会抛到全局，因此id与localList.length产生关联会导致冲突
            // c.id = uuid();
            c.points = [];
            c.label = '';
            c.responsibility = username;
            c.properties = {};

            return c;
        },
        undo() {
            console.info('p-painter-contours.undo ...', this.local, this.localList);
            if (this.local && this.local.points && this.local.points.length) {
                this.local.points.pop();
                if (!this.local.points.length) this.local = {};
            } else if (this.localList && this.localList.length) {
                this.localList.pop();
            }
            // remove tape measure.
            if (this.tapes && this.tapes.length) {
                this.tapes.pop();
            }
            this.refresh(true);
        },

        isCanvasBlank() {
            if (!this.blankCanvas) this.blankCanvas = document.createElement('canvas');
            let canvas = this.$refs.canvas;
            this.blankCanvas.width = canvas.width;
            this.blankCanvas.height = canvas.height;

            return canvas.toDataURL() == this.blankCanvas.toDataURL();
        },

        // Cache for offscrren render.
        setCtxCache(key, canvas) {
            if (!this.ctxCache) this.ctxCache = { key: '', val: null };
            if (this.ctxCache.key !== key) {
                this.ctxCache.key = key;
                this.ctxCache.val = canvas;
            }
            return this.ctxCache.val;
        },
        getCtxCache(key) {
            if (this.ctxCache && this.ctxCache.key === key) return this.ctxCache.val;
            return null;
        }
    }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<!-- <style scoped lang="scss"> -->
<style lang="scss">
.p-painter-contours {
    width: 100%;
    height: 100%;
}
</style>
